﻿<cfscript>

/** 
* Security Frameworks - CAS Ticket Validator v1.0
*
* @displayname "public.service.session.cas10TicketValidator" 
* @hint "CAS Ticket Validator v1.0" 
* 
* @Output false
* 
* @accessors true
*/

component {

	property type="string" name="CasServerUrlPrefix" hint="CAS 服务器地址前缀";
	
	/**
	* @hint "初始化对象"
	* 
	* @Output false
	* 
	* @casServerUrlPrefix "CAS 服务器地址前缀"
	*/
	public function init( required string casServerUrlPrefix ) {
		
		setCasServerUrlPrefix( arguments.casServerUrlPrefix );
		
	}
	
	/**
	* @hint "CAS 验证后回馈信息"
	* 
	* @Output false
	* 
	* @ticket "Service Ticket ID"
	* @serviceUrl "单点认证的服务地址"
	*/
	public struct function validate( required string ticket, required string serviceUrl ) {
		
		var result = { 
						"userId" = parseResponseFromServer( 
										retrieveResponseFromServer( arguments.ticket, arguments.serviceUrl ) 
										) 
					};
		
		return result;
	}
	
	/*	
	=======================================================
	Private Method
	=======================================================
	*/

	/**
	* @hint "构建 CAS 验证地址"
	* 
	* @Output false
	* 
	* @ticket "Service Ticket ID"
	* @serviceUrl "单点认证的服务地址"
	*/
	private string function constructValidationUrl( required string ticket, required string serviceUrl ) {
		
		var validationURL = getCasServerUrlPrefix() & "validate";
		
		/* 添加 Ticket 参数 */
		validationURL = validationURL & "?ticket=" & arguments.ticket;

		/* 添加 Service 参数 */
		validationURL = validationURL & "&service=" & URLEncodedFormat( arguments.serviceUrl, "utf-8" );
		
		return validationURL;
	}
	
	/**
	* @hint "从 CAS 服务器读取反馈数据"
	* 
	* @Output false
	* 
	* @ticket "Service Ticket ID"
	* @serviceUrl "单点认证的服务地址"
	*/
	private string function retrieveResponseFromServer( required string ticket, required string serviceUrl ) {

		var serverResponse = "";
		
		try {
		
			/* create new http service */
			var httpObj = new http();
	
			/* set attributes using implicit setters */
			httpObj.setMethod("get");
			httpObj.setCharset("utf-8");
			httpObj.setUrl( constructValidationUrl( arguments.ticket, arguments.serviceUrl ) );
	
			serverResponse = httpObj.send().getPrefix().Filecontent;
			
			return serverResponse;
		
		}
		catch ( any exception ) {
			throw( message="Unable to contract CAS Server." );
		}

	}

	/**
	* @hint "处理 CAS 服务器反馈数据, 返回认证用户 userId"
	* 
	* @Output false
	* 
	* @response "CAS 服务器反馈数据"
	*/	
	private string function parseResponseFromServer( required string response ) {
		
		if ( len( arguments.response ) ) {
				
			if ( listFirst( arguments.response, CHR(10) ) eq "yes" ) {
				return listLast( arguments.response, CHR(10) );
			}
			else {
				throw( message="CAS Server could not validate ticket." );
			}
				
		}
		else {
			throw( message="The CAS server returned no response." );
		}
		
	}
	
	
}

</cfscript>